<template>
    <div class="row mb-3">
        <label
            :for="inputId"
            :class="[wide ? 'col-sm-4' : 'col-sm-2', isCheckbox ? 'form-check-label' : 'col-form-label']"
        >
            {{ label }}
            <BIconInfoCircle v-if="tooltip !== undefined" v-tooltip :title="tooltip" />
        </label>
        <div :class="[wide ? 'col-sm-8' : 'col-sm-10']">
            <div v-if="!isTextarea" :class="{ 'form-check form-switch': isCheckbox, 'input-group': postfix || prefix }">
                <span v-if="prefix" class="input-group-text" :id="descriptionId">
                    {{ prefix }}
                </span>
                <input
                    v-model="model"
                    :class="[isCheckbox ? 'form-check-input' : 'form-control']"
                    :id="inputId"
                    :placeholder="placeholder"
                    :type="type"
                    :minlength="minlength"
                    :maxlength="maxlength"
                    :min="min"
                    :max="max"
                    :step="step"
                    :disabled="disabled"
                    :aria-describedby="descriptionId"
                />
                <span v-if="postfix" class="input-group-text" :id="descriptionId">
                    {{ postfix }}
                </span>
                <slot />
            </div>
            <div v-else>
                <textarea
                    v-model="model"
                    class="form-control"
                    :id="inputId"
                    :maxlength="maxlength"
                    :rows="rows"
                    :disabled="disabled"
                    :placeholder="placeholder"
                />
            </div>
        </div>
    </div>
</template>

<script lang="ts">
import { BIconInfoCircle } from 'bootstrap-icons-vue';
import { defineComponent } from 'vue';

export default defineComponent({
    components: {
        BIconInfoCircle,
    },
    props: {
        modelValue: [String, Number, Boolean, Date],
        label: String,
        placeholder: String,
        type: String,
        minlength: String,
        maxlength: String,
        min: String,
        max: String,
        step: String,
        rows: String,
        disabled: Boolean,
        postfix: String,
        prefix: String,
        wide: Boolean,
        tooltip: String,
    },
    data() {
        return {};
    },
    computed: {
        model: {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            get(): any {
                if (this.type === 'checkbox') return !!this.modelValue;
                return this.modelValue;
            },
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            set(value: any) {
                this.$emit('update:modelValue', value);
            },
        },
        uniqueLabel() {
            // normally, the label is sufficient to build a unique id
            // if two inputs with the same label text on one page is required,
            // use a unique placeholder even if it is a checkbox
            return (
                this.label?.replace(/[^A-Za-z0-9]/g, '') +
                (this.placeholder ? this.placeholder.replace(/[^A-Za-z0-9]/g, '') : '')
            );
        },
        inputId() {
            return 'input' + this.uniqueLabel;
        },
        descriptionId() {
            return 'desc' + this.uniqueLabel;
        },
        isTextarea() {
            return this.type === 'textarea';
        },
        isCheckbox() {
            return this.type === 'checkbox';
        },
    },
});
</script>
